package com.auctionhaus

import com.auctionhaus.*

class ListingIntegrationTests extends GroovyTestCase {
    transient Date testFutureDate =  new Date(System.currentTimeMillis()+10000);
    transient Date creationDate = new Date();

    protected void setUp() {
        super.setUp()

    }

    protected void tearDown() {
        super.tearDown()

        Bid.findAll().each {x -> x.delete() }
        Listing.findAll().each {x -> x.delete() }
        Customer.findAll().each {x -> x.delete() }
    }


    //L-4: Updating a Listing should not update the seller's information (integration test)
    def testUpdateListingDoesNotUpdateSeller = {->

        def customerSeller = new Customer(emailAddress: "original@gmail.com", password: "abcdefg", date: creationDate)
        if (!customerSeller.save(failOnError: true))
            customerSeller = Customer.findByEmailAddress("original@gmail.com")
        def auctionListing = new Listing(creationDate:"testCurrentDate", listName: 'Jeep Grand Cherokee',
                description: 'Shiny',
                endDateTime: testFutureDate,
                startBidPrice: 1,
                seller: customerSeller)
        auctionListing.save(failOnError: true)
        assertEquals auctionListing.validate()

        //find the customer and attempt to find a customer by the original email address
        def foundCustomer = Customer.findByEmailAddress("original@gmail.com")
        assertEquals foundCustomer.emailAddress, "original@gmail.com"
        assertEquals foundCustomer.password, "abcdefg"

        //modify the listing and attempt to find a customer by the original email address and listing
        auctionListing.description = 'Rusty'
        auctionListing.save(failOnError:true);

        //find the customer by email address after listing modified
        def foundCustomerByEmail = Customer.findByEmailAddress("original@gmail.com")
        assertEquals foundCustomerByEmail.emailAddress, "original@gmail.com"
        assertEquals foundCustomerByEmail.password, "abcdefg"

        //find the customer by listing does not work with a modified listing
        def foundCustomerByListing = Customer.findByListings(auctionListing)
        assertNull foundCustomerByListing
    }
    //L-5: Updating a seller's information should not modify any properties of that seller's listings (integration test)
    void testUpdateSellerDoesNotUpdateListing() {

        def customerSeller = new Customer (emailAddress: "seller@gmail.com", password: "abcdefg", date:new Date())
        if (!customerSeller.save(failOnError: true))
             customerSeller = Customer.findByEmailAddress("original@gmail.com")
        def auctionListing = new Listing(creationDate:"testCurrentDate", listName:'Jeep Grand Cherokee',
                                            description:'Shiny',
                                            endDateTime:testFutureDate,
                                            startBidPrice:1,
                                            seller:customerSeller)
        if (!auctionListing.save(failOnError: true))
              auctionListing = Listing.findByListName("Jeep Grand Cherokee")

        def foundListing = Listing.findByDescription('Shiny')
        assertNotNull foundListing
        assertEquals foundListing.listName, 'Jeep Grand Cherokee'
        assertEquals foundListing.description, 'Shiny'
        assertEquals foundListing.endDateTime, testFutureDate
        assertEquals foundListing.endDateTime, testFutureDate
        assertEquals foundListing.startBidPrice, 1

        //modify the seller and attempt to find the listing
        customerSeller.password = "changed"
        customerSeller.save(failOnError: true);
        def foundListingAfterSellerModified = Listing.findByDescription('Shiny')
        assertNotNull foundListingAfterSellerModified
        assertNotNull foundListingAfterSellerModified
        assertEquals foundListingAfterSellerModified.listName, 'Jeep Grand Cherokee'
        assertEquals foundListingAfterSellerModified.description, 'Shiny'
        assertEquals foundListingAfterSellerModified.endDateTime, testFutureDate
        assertEquals foundListingAfterSellerModified.endDateTime, testFutureDate
        assertEquals foundListingAfterSellerModified.startBidPrice, 1


    }
    //L-6: Listing descriptions must be less than 256 characters (integration test)
    void testDescriptionLengthLessThanMax() {
        def customerSeller = new Customer (emailAddress: "seller@gmail.com", password: "abcdefg", date:new Date()).save()
        def auctionListing = new Listing(creationDate:"testCurrentDate", listName:'Jeep Grand Cherokee',
                                            description:'Shiny',
                                            endDateTime:testFutureDate,
                                            startBidPrice:1,
                                            seller:customerSeller).save()

        assertTrue 'This should work!', auctionListing.validate()

        for (x in 0..257){
            auctionListing.description += '${x}'
        }
        assertFalse 'This should not work!', auctionListing.validate()

    }
    //L-7: Listing end date/time must be in the future (integration test)
    void testEndDateTimeInFuture() {
        def customerSeller = new Customer (emailAddress: "seller@gmail.com",
                                            password: "abcdefg",
                                            date:new Date()).save()
        def auctionListing = new Listing(creationDate:"testCurrentDate", listName:'Jeep Grand Cherokee',
                                            description:'Shiny',
                                            endDateTime:new Date(System.currentTimeMillis() - 1),
                                            startBidPrice:1,
                                            seller:customerSeller)

        assertFalse 'This should not work!', auctionListing.validate()

        auctionListing.endDateTime = new Date(System.currentTimeMillis() + 10)
        assertTrue 'This should work!', auctionListing.validate()

    }
    //L-8: Listing name must be less than 64 characters (integration test)
    void testListingNameLengthLessThanMax() {

        def customerSeller = new Customer (emailAddress: "seller@gmail.com", password: "abcdefg", date:new Date()).save()
        def auctionListing = new Listing(creationDate:"testCurrentDate", listName:'Jeep Grand Cherokee',
                                            description:'Shiny',
                                            endDateTime:testFutureDate,
                                            startBidPrice:1,
                                            seller:customerSeller).save(flush:true)

        assertTrue 'This should work!', auctionListing.validate()
        auctionListing.listName = ''

        for (x in 0..63){
            auctionListing.listName += 'a'
            assertTrue 'This should work!', auctionListing.validate()
        }
        auctionListing.listName += 'a'
        assertFalse 'This should not work!', auctionListing.validate()
    }
    //L-9: Listing has a nullable field for the winner (Customer) (integration test)
    void testOptionalWinner() {
        def customerSeller = new Customer (emailAddress: "seller@gmail.com", password: "abcdefg", date:new Date()).save()
        def auctionListing = new Listing(creationDate:"testCurrentDate", listName:'Jeep Grand Cherokee',
                                            description:'Shiny',
                                            endDateTime:testFutureDate,
                                            startBidPrice:1,
                                            seller:customerSeller).save()
        assertTrue 'This should work!', auctionListing.validate()

        def customerWinner = new Customer (emailAddress: "bidder@gmail.com", password: "abcdefg", date:new Date()).save()

        auctionListing.winner =  customerWinner;
        assertTrue 'This should work!', auctionListing.validate()


    }
}
